import { Merchant } from '@app/db/entities/Merchant';
import { WithdrawalRecord } from '@app/db/entities/WithdrawalRecord';
import { Injectable } from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';
import * as dayjs from 'dayjs';
import { DbService } from '@app/db';

@Injectable()
export class MerchantService {
    constructor(
        @InjectDataSource() protected readonly dataSource: DataSource,
        private db:DbService
    ){}

    async statistics(merchantId:number) {
        const currentDate = new Date();  
        const todayTime = Math.floor(currentDate.setHours(0, 0, 0, 0) / 1000);
        const yesterdayTime = dayjs.unix(todayTime).subtract(1, 'day').unix()
        const total = await this.db.merchant.findOne({id : merchantId})
        const today = await this.db.merchantDailyIncome.findOne({date : todayTime, merchantId : merchantId}) //今日的收入
        const yesterday = await this.db.merchantDailyIncome.findOne({date : yesterdayTime, merchantId : merchantId}) //昨日的收入



        const onlineDeviceCount = await this.db.device.createQueryBuilder().where({connectStatus : 1}).andWhere(`JSON_CONTAINS(owners, '${merchantId}')`).getCount()
        const offlineDeviceCount = await this.db.device.createQueryBuilder().where({connectStatus : 0}).andWhere(`JSON_CONTAINS(owners, '${merchantId}')`).getCount()

        return {
            onlineDeviceCount,
            offlineDeviceCount,
            total,
            today,
            yesterday
        }

    }


    async applyWithdrawal(amount:number, memberId:number, tenantId:number) {

        const queryRunner = await this.dataSource.createQueryRunner()
        await queryRunner.connect();
        await queryRunner.startTransaction();


        try {
            let merchant = await queryRunner.manager.findOne<Merchant>(Merchant, {
                where : {id : tenantId},
                select : ['account', 'bank', 'payee', 'amount', 'frozenAmount'],
                lock : {
                    mode : 'pessimistic_read'
                }
            })

            if(!merchant || !merchant.payee || !merchant.bank || !merchant.account) {
                await queryRunner.rollbackTransaction()
                return null
            }

            const balance = Number(merchant.amount)
            if(balance < amount) {
                await queryRunner.rollbackTransaction()
                return -1
            }

            const record:KeyToValueType<WithdrawalRecord> = {
                createTime : Math.floor(Date.now() / 1000),
                memberId : memberId,
                merchantId : tenantId,
                amount : String(amount),
                payee : merchant.payee,
                bank : merchant.bank,
                account : merchant.account,
                status : 0
            }

            const r1 = await queryRunner.manager.update<Merchant>(Merchant, {id : tenantId}, {
                amount : (balance - amount).toFixed(2),
                frozenAmount : (Number(merchant.frozenAmount) + amount).toFixed(2)
            })

            if(r1.affected < 1) {
                await queryRunner.rollbackTransaction();
                return -2
            }

            const { raw } = await queryRunner.manager.insert<WithdrawalRecord>(WithdrawalRecord, record)
            if(!raw || raw.affectedRows < 1) {
                await queryRunner.rollbackTransaction();
                return -3
            }

            await queryRunner.commitTransaction()

            return true

        } catch (error) {
            await queryRunner.rollbackTransaction();
            return null
        } finally {
            await queryRunner.release();
        }
    }

    //撤销提现
    async revokeWithdrawal(id:number) {
        const queryRunner = await this.dataSource.createQueryRunner()
        await queryRunner.connect();
        await queryRunner.startTransaction();

        try {
            let record = await queryRunner.manager.findOne<WithdrawalRecord>(WithdrawalRecord, {
                where : {id : id},
                select : ['merchantId', 'amount', 'status'],
                lock : {
                    mode : 'pessimistic_read'
                }
            })

            if(!record || record.status != 0) {
                await queryRunner.rollbackTransaction()
                return null
            }

            let merchant = await queryRunner.manager.findOne<Merchant>(Merchant, {
                where : {id : record.merchantId},
                select : ['amount', 'frozenAmount'],
                lock : {
                    mode : 'pessimistic_read'
                }
            })

            if(!merchant) {
                await queryRunner.rollbackTransaction()
                return null
            }

            const r1 = await queryRunner.manager.update<WithdrawalRecord>(WithdrawalRecord, {id : id}, {
                status : 3
            })

            if(r1.affected < 1) {
                await queryRunner.rollbackTransaction();
                return -1
            }

            const amount = Number(record.amount)


            const r2 = await queryRunner.manager.update<Merchant>(Merchant, {id : record.merchantId}, {
                amount : (Number(merchant.amount) + amount).toFixed(2),
                frozenAmount : (Number(merchant.frozenAmount) - amount).toFixed(2),
            })

            if(r2.affected < 1) {
                await queryRunner.rollbackTransaction();
                return -2
            }

            await queryRunner.commitTransaction()

            return true

        } catch (error) {
            await queryRunner.rollbackTransaction();
            return null
        } finally {
            await queryRunner.release();
        }
    }
}
